package cn.wolfcode.wolf2w.business.service.impl;


import cn.wolfcode.wolf2w.business.api.domain.StrategyCatalog;
import cn.wolfcode.wolf2w.business.api.domain.StrategyContent;
import cn.wolfcode.wolf2w.business.api.domain.StrategyTheme;
import cn.wolfcode.wolf2w.business.mapper.StrategyCatalogMapper;
import cn.wolfcode.wolf2w.business.mapper.StrategyContentMapper;
import cn.wolfcode.wolf2w.business.mapper.StrategyThemeMapper;
import cn.wolfcode.wolf2w.business.api.domain.Strategy;
import cn.wolfcode.wolf2w.business.mapper.StrategyMapper;
import cn.wolfcode.wolf2w.business.query.StrategyQuery;
import cn.wolfcode.wolf2w.business.service.IStrategyService;
import cn.wolfcode.wolf2w.business.util.DateUtil;
import cn.wolfcode.wolf2w.business.vo.ThemeVO;
import cn.wolfcode.wolf2w.common.redis.service.RedisService;
import cn.wolfcode.wolf2w.common.redis.util.RedisKeys;
import cn.wolfcode.wolf2w.destination.entity.TaDestination;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.weaver.ast.Var;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 攻略Service业务层处理
 * 
 * @author hyz
 * @date 2024-07-24
 */
@Service
@Transactional
public class StrategyServiceImpl extends ServiceImpl<StrategyMapper,Strategy> implements IStrategyService {

    @Autowired
    private StrategyCatalogMapper strategyCatalogMapper;

    @Autowired
    private StrategyThemeMapper strategyThemeMapper;

    @Autowired
    private StrategyContentMapper strategyContentMapper;

    @Autowired
    private StrategyMapper strategyMapper;

    @Autowired
    private RedisService redisService;


    @Autowired
    private AmqpTemplate amqpTemplate;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public IPage<Strategy> queryPage(StrategyQuery qo) {
        IPage<Strategy> page = new Page<>(qo.getCurrentPage(), qo.getPageSize());
        return lambdaQuery()
                .eq(qo.getThemeId() != null,Strategy::getThemeId,qo.getThemeId())
                .eq(qo.getCatalogId() != null,Strategy::getCatalogId,qo.getCatalogId())
                .like(!StringUtils.isBlank(qo.getTitle()),Strategy::getTitle,qo.getTitle())
                .eq(qo.getIsabroad() != null,Strategy::getIsabroad,qo.getIsabroad())
                .eq(qo.getState() != null,Strategy::getState,qo.getState())
                .eq(qo.getRefid() != null && (qo.getType() == 1 || qo.getType() == 2),Strategy::getDestId,qo.getRefid())
                .eq(qo.getRefid() != null && (qo.getType() == 3),Strategy::getThemeId,qo.getRefid())
                .page(page);
    }

    @Override
    public List<Strategy> queryViewnumTop3(Long destId) {
        List<Strategy> list = lambdaQuery().eq(Strategy::getDestId, destId)
                .eq(Strategy::getState, 1)
                .orderByDesc(Strategy::getViewnum)
                .last("limit 3")
                .list();
        return list;
    }

    @Override
    public boolean strategySave(Strategy strategy) {
        StrategyCatalog catalog = strategyCatalogMapper.selectById(strategy.getCatalogId());
        strategy.setDestId(catalog.getDestId());
        strategy.setDestName(catalog.getDestName());
        strategy.setCatalogName(catalog.getName());
        StrategyTheme theme = strategyThemeMapper.selectById(strategy.getThemeId());
        strategy.setThemeName(theme.getName());
        strategy.setCreateTime(new Date());

//        strategy.setIsabroad(0l);
        strategy.setViewnum(0l);
        strategy.setReplynum(0l);
        strategy.setFavornum(0l);
        strategy.setSharenum(0l);
        strategy.setThumbsupnum(0l);
        save(strategy);
        StrategyContent strategyContent = new StrategyContent();
        strategyContent.setId(strategy.getId());
        strategyContent.setContent(strategy.getContent().getContent());
        strategyContentMapper.insert(strategyContent);

        //TODO: 发消息到MQ
        String message = JSON.toJSONString(strategy);
        String key = RedisKeys.ES_DATA.join("key");
        redisTemplate.opsForZSet().add(key,message,System.currentTimeMillis());
        amqpTemplate.convertAndSend("esTopicExchange","esKey",message);

        return true;
    }

    @Override
    public Strategy getDetailById(Long id) {
        Strategy strategy = strategyMapper.selectById(id);
        StrategyContent strategyContent = strategyContentMapper.selectById(id);
        strategy.setContent(strategyContent);
        return strategy;
    }

    @Override
    public List<ThemeVO> queryThemeVO() {
        QueryWrapper<Strategy> qw = new QueryWrapper<>();
        qw.select("theme_name, GROUP_CONCAT(DISTINCT dest_id) ids, GROUP_CONCAT(DISTINCT dest_name) names");
        qw.groupBy("theme_name");
        List<Map<String, Object>> maps = strategyMapper.selectMaps(qw);
        List<ThemeVO> vos = new ArrayList<>();
        for (Map<String, Object> map : maps) {
            String themeName = (String) map.get("theme_name");
            String ids = (String) map.get("ids");
            String names = (String)map.get("names");
            String[] idArr = ids.split(",");
            String[] nameArr = names.split(",");
            List<TaDestination> dests = new ArrayList<>();
            for (int i = 0; i < idArr.length; i++) {
                Long id = Long.valueOf(idArr[i]);
                String name = nameArr[i];
                TaDestination dest = new TaDestination();
                dest.setId(id);
                dest.setName(name);
                dests.add(dest);
            }
            ThemeVO themeVO = new ThemeVO();
            themeVO.setDests(dests);
            themeVO.setThemeName(themeName);
            vos.add(themeVO);
        }
        return vos;
    }

    private String strategyHashInit(Long sid){
        String key = RedisKeys.STRATEGY_STATIS_HASH.join(sid.toString());
        Boolean b = redisService.hasKey(key);
        if(!b){
            Strategy strategy = strategyMapper.selectById(sid);
//            Map<String,Object> map = new HashMap<>();
//            map.put("viewnum",Integer.valueOf(strategy.getViewnum().toString()));
//            map.put("sharenum",Integer.valueOf(strategy.getSharenum().toString()));
//            map.put("favornum",Integer.valueOf(strategy.getFavornum().toString()));
//            map.put("replynum",Integer.valueOf(strategy.getReplynum().toString()));
//            map.put("thumbsupnum",Integer.valueOf(strategy.getThumbsupnum().toString()));
//            map.put("id",strategy.getId());
            Map<String, Object> map = strategy2Map(strategy);
            redisService.setCacheMap(key,map);
        }
        return key;
    }

    @Override
    public Map<String, Object> viewnumIncr(Long sid) {
        String key = strategyHashInit(sid);
        redisService.incrementCacheMapValue(key,"viewnum",1);
        Map<String, Object> result = redisService.getCacheMap(key);
        return result;
    }

    @Override
    public void statisHashDataPersistence() {
//        System.out.println("消息持久化redis data");
        Collection<String> keys = redisService.keys(RedisKeys.STRATEGY_STATIS_HASH.join("*"));
        if(keys != null && keys.size() > 0){
            for (String key : keys) {
                Map<String, Object> map = redisService.getCacheMap(key);
                UpdateWrapper<Strategy> uw = new UpdateWrapper<>();
                uw.eq("id",map.get("id"));
                uw.set("viewnum",map.get("viewnum"));
                uw.set("replynum",map.get("replynum"));
                uw.set("favornum",map.get("favornum"));
                uw.set("sharenum",map.get("sharenum"));
                uw.set("thumbsupnum",map.get("thumbsupnum"));
                strategyMapper.update(null,uw);
            }
        }
    }

    private Map<String,Object> strategy2Map(Strategy strategy){
        Map<String,Object> map = new HashMap<>();
        map.put("viewnum",Integer.valueOf(strategy.getViewnum().toString()));
        map.put("sharenum",Integer.valueOf(strategy.getSharenum().toString()));
        map.put("favornum",Integer.valueOf(strategy.getFavornum().toString()));
        map.put("replynum",Integer.valueOf(strategy.getReplynum().toString()));
        map.put("thumbsupnum",Integer.valueOf(strategy.getThumbsupnum().toString()));
        map.put("id",strategy.getId());
        return map;
    }

    @Override
    public void statisHashInit() {
        List<Strategy> strategies = strategyMapper.selectList(null);
        for (Strategy strategy : strategies) {
            String key = RedisKeys.STRATEGY_STATIS_HASH.join(strategy.getId().toString());
            if(redisService.hasKey(key)){
                continue;
            }
            Map<String, Object> map = strategy2Map(strategy);
            redisService.setCacheMap(key,map);
        }
    }

    @Override
    public Map<String, Object> favor(Long sid, Long uid) {
        String key = RedisKeys.USER_STRATEGY_FAVOR.join(uid.toString());
        Boolean b = redisService.hasKey(key);
        if(!b){ //用户没有收藏任何文章
            Set<Long> sidSet = new HashSet<>();
            sidSet.add(-1l);
            redisService.setCacheSet(key,sidSet);
        }
        boolean flg = redisService.isCacheSetContains(key, sid);
//        boolean resultFlg = false;
        String statisKey = RedisKeys.STRATEGY_STATIS_HASH.join(sid.toString());
        if(flg){
            //当前用户收藏过该文章
            redisService.incrementCacheMapValue(statisKey,"favornum",-1);
            redisService.deleteCacheSetValue(key,sid);
        }else{
            redisService.incrementCacheMapValue(statisKey,"favornum",1);
            redisService.addCacheSetValue(key,sid);
        }
        Map<String, Object> map = redisService.getCacheMap(statisKey);
        map.put("result",!flg);
        return map;
    }

    @Override
    public boolean isUserFavor(Long sid, Long uid) {
        String key = RedisKeys.USER_STRATEGY_FAVOR.join(uid.toString());
        Boolean b = redisService.hasKey(key);
        if(!b){ //用户没有收藏任何文章
            Set<Long> sidSet = new HashSet<>();
            sidSet.add(-1l);
            redisService.setCacheSet(key,sidSet);
        }
        boolean flg = redisService.isCacheSetContains(key, sid);
        return flg;
    }

//    @Override
//    public void replynumIncr(Long sid) {
//        String key = strategyHashInit(sid);
//        redisService.incrementCacheMapValue(key,"replynum",1);
//    }

    @Override
    public  Map<String,Object> replynumIncr(Long sid) {
        String key = strategyHashInit(sid);
        redisService.incrementCacheMapValue(key,"replynum",1);
        Map<String,Object> result = redisService.getCacheMap(key);
        return result;
    }

    @Override
    public Map<String, Object> thumbsup(Long sid, Long uid) {
        String key = RedisKeys.STRATEGY_THUMBSUP.join(sid.toString(), uid.toString());
        Date now = new Date();
        Date end = DateUtil.getEndDate(now);
        long time = DateUtil.getBetweenTime(now,end);
//        Boolean flg = redisService.hasKey(key);
//        if(!flg){
//            redisService.setCacheObject(key,0,time, TimeUnit.SECONDS);
//        }
//        if(time > 0){
//
//        }
        redisService.setNXCacheObject(key,0,time, TimeUnit.SECONDS);
        Long count = redisService.incrCacheObject(key);
//        Map<String,Object> map = new HashMap<>();
        boolean b = true;
        String statisKey = RedisKeys.STRATEGY_STATIS_HASH.join(sid.toString());
        if(count > 5){
            //今天不能再点赞了
//            map.put("result",false);
            b = false;
        }else{
            //可以点赞，点赞数+1
//            map.put("result",true);
            redisService.incrementCacheMapValue(statisKey,"thumbsupnum",1);
        }
        Map<String,Object> map = redisService.getCacheMap(statisKey);
        map.put("result",b);
        return map;
    }

}
